package com.liuya.common;

import java.io.IOException;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.util.WebUtils;

/**
 * Web层辅助类
 *
 * @author liuya
 * @version 0.1.0
 */
public final class WebUtil {
    private WebUtil() {
    }

    public static Locale getClientLocal(){
        return LocaleContextHolder.getLocale();
    }

    public static String getClientLanguage(){
        return LocaleContextHolder.getLocale().toString();
    }

    public static void forward(HttpServletRequest req, HttpServletResponse resp, String url) throws ServletException, IOException {
        RequestDispatcher rd = req.getRequestDispatcher(url);
        rd.forward(req, resp);
    }

    /**
     * 获取指定Cookie的值
     *
     * @param request      cookie集合
     * @param cookieName   cookie名字
     * @param defaultValue 缺省值
     * @return
     */
    public static final String getCookieValue(HttpServletRequest request, String cookieName, String defaultValue) {
        Cookie cookie = WebUtils.getCookie(request, cookieName);
        if (cookie == null) {
            return defaultValue;
        }
        return cookie.getValue();
    }

    /**
     * 保存当前用户
     */
    public static final void setCurrentUser(Object user) {
        setSession(Constants.CURRENT_USER, user);
    }

    /**
     * 获取当前用户
     */
    public static final Object getCurrentUser() {
        if (null == ThreadContext.getSubject()) {
            return null;
        }

        Subject currentUser = SecurityUtils.getSubject();
        if (null != currentUser) {
            Session session = currentUser.getSession();
            if (null != session) {
                return (String) session.getAttribute(Constants.CURRENT_USER);
            }
        }
        return null;
    }

    public static final String getCurrentUserId() {
        if (null == ThreadContext.getSubject()) {
            return null;
        }
        try{
            Subject currentUser = SecurityUtils.getSubject();
            if (null != currentUser) {
                Object session = currentUser.getSession();
                if (null != session) {
                    Session sess = ((Session)session);
                    Object uid = sess.getAttribute(Constants.CURRENT_USER_ID);
                    if(uid==null || uid.equals(""))
                        return "";
                    return (String) uid;
                }
            }
        } catch(Exception e){
            return null;
        }

        return null;
    }

    /**
     * 将一些数据放到ShiroSession中,以便于其它地方使用
     * 比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到
     * @see
     */
    public static final void setSession(Object key, Object value) {
        Subject currentUser = SecurityUtils.getSubject();
        if (null != currentUser) {
            Session session = currentUser.getSession();
            if (null != session) {
                session.setAttribute(key, value);
            }
        }
    }

    /**
     * 移除当前用户
     */
    public static final void removeCurrentUser(HttpServletRequest request) {
        request.getSession().removeAttribute(Constants.CURRENT_USER);
    }

    /**
     * 获得国际化信息
     *
     * @param key     键
     * @param request
     * @return
     */
    public static final String getApplicationResource(String key, HttpServletRequest request) {
        ResourceBundle resourceBundle = ResourceBundle.getBundle("ApplicationResources", request.getLocale());
        return resourceBundle.getString(key);
    }

    /**
     * 获得请求中的所有参数Map
     *
     * @param request
     * @return
     */
    public static final Map<String, Object> getParameters(HttpServletRequest request) {
        return WebUtils.getParametersStartingWith(request, null);
    }

    /**
     * 获取客户端IP
     */
    public static final String getHost(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if ("127.0.0.1".equals(ip)) {
            InetAddress inet = null;
            try { // 根据网卡取本机配置的IP
                inet = InetAddress.getLocalHost();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
            ip = inet.getHostAddress();
        }
        // 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(",") > 0) {
                ip = ip.substring(0, ip.indexOf(","));
            }
        }
        return ip;
    }

    public static String getStringParameter(HttpServletRequest req, String paramName) {
        return getStringParameter(req, paramName, "");
    }

    public static String getStringParameter(HttpServletRequest req, String paramName, String defaultValue) {
        String value = req.getParameter(paramName);
        if (StringUtil.isEmpty(value)) {
            return defaultValue;
        }
        return value;
    }

    public static int getIntParameter(HttpServletRequest req, String paramName, int defaultValue) {
        String value = req.getParameter(paramName);
        if (StringUtil.isEmpty(value)) {
            return defaultValue;
        } else {
            try {
                return Integer.parseInt(value);
            } catch (Exception e) {
                return defaultValue;
            }
        }
    }

    public static boolean getBooleanParameter(HttpServletRequest req, String paramName, boolean defaultValue) {
        String value = req.getParameter(paramName);
        if (StringUtil.isEmpty(value)) {
            return defaultValue;
        } else {
            try {
                return Boolean.parseBoolean(value);
            } catch (Exception e) {
                return defaultValue;
            }
        }
    }

    public static long getLongParameter(HttpServletRequest req, String paramName, long defaultValue) {
        String value = req.getParameter(paramName);
        if (StringUtil.isEmpty(value)) {
            return defaultValue;
        } else {
            try {
                return Long.parseLong(value);
            } catch (Exception e) {
                return defaultValue;
            }
        }
    }

    public static double getDoubleParameter(HttpServletRequest req, String paramName, double defaultValue) {
        String value = req.getParameter(paramName);
        if (StringUtil.isEmpty(value)) {
            return defaultValue;
        } else {
            try {
                return Double.parseDouble(value);
            } catch (Exception e) {
                return defaultValue;
            }
        }
    }

    public static final <K> List<K> covert(Class<K> T, HttpServletRequest request) {
        try {

            List<K> objectList = new LinkedList<K>();
            // Object obj = T.newInstance();
            // 获取类的方法集合
            Set<Method> methodSet = get_declared_methods(T);
            Map<String, String[]> stringMap = request.getParameterMap();
            Integer valueSize = paramSize(methodSet, stringMap);
            System.out.println(T.getName() + " Max Length:" + valueSize);
            for (int i = 0; i < valueSize; i++) {
                K object = T.newInstance();
                for (Method method : methodSet) {
                    String key = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
                    String[] value = stringMap.get(key);
                    if (value != null && i < value.length) {
                        Class<?>[] type = method.getParameterTypes();
                        Object[] param_value = new Object[]{TypeParseUtil.convert(value[i], type[0], null)};
                        method.invoke(object, param_value);
                    }
                }
                objectList.add(object);
            }
            return objectList;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

    /**
     * 取自定义Set方法
     *
     * @param T
     * @return
     */
    private static final <T> Set<Method> get_declared_methods(Class<T> T) {
        Method[] methods = T.getDeclaredMethods();
        Set<Method> methodSet = new HashSet<Method>();
        for (Method method : methods) {
            if (method.getName().startsWith("set")) {
                methodSet.add(method);
            }
        }
        return methodSet;
    }

    private static final Integer paramSize(Set<Method> methodSet, Map<String, String[]> stringMap) {
        Integer size = 0;
        for (Method method : methodSet) {
            String key = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
            Integer tempSize = 0;
            if (stringMap.containsKey(key)) {
                tempSize = stringMap.get(key).length;
            }
            if (tempSize > size)
                size = tempSize;
        }
        return size;
    }
}
